/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet;

import jakarta.servlet.ServletRequest;
import jakarta.servlet.http.HttpServletRequest;

import org.springframework.lang.Nullable;

/**
 *
 * <p>
 *     在 Spring MVC 中，HandlerMapping 是一个关键的接口，它定义了如何将传入的 HTTP 请求映射到相应的处理器（通常是一个控制器方法）。
 *     HandlerMapping 的主要职责是根据请求的信息（如 URL、HTTP 方法等）来查找最适合处理该请求的处理器，并提供给 DispatcherServlet 用于进一步处理。以下是关于 HandlerMapping 的详细分析：
 *	1. 作用与职责
 * 		请求分发：HandlerMapping 接收来自 DispatcherServlet 的 HTTP 请求，并负责找到能够处理这个请求的处理器。
 * 		URL 路径匹配：解析请求的 URL 路径，以确定哪个控制器方法应该被调用来处理请求。
 * 		HTTP 方法匹配：确保请求的 HTTP 方法（GET、POST 等）与控制器方法上指定的方法相匹配。
 * 		参数绑定：一些 HandlerMapping 实现还可以帮助准备请求参数，以便它们可以正确地传递给处理器方法。
 *
 * 	2. 实现类
 * 		Spring 提供了多种 HandlerMapping 的实现类，每种实现都有其特定的功能和适用场景：
 *
 * 		RequestMappingHandlerMapping：这是最常用的实现之一，它基于注解（如 @RequestMapping 及其变体 @GetMapping, @PostMapping 等）来映射请求到控制器方法。它是 Spring MVC 默认的 HandlerMapping，适用于大多数应用程序。
 * 		BeanNameUrlHandlerMapping：这种映射方式依赖于 Bean 名称与 URL 模式之间的简单对应关系。如果有一个名为 myController 的 Bean，那么它将自动处理 /myController 的请求。
 * 		SimpleUrlHandlerMapping：允许通过 XML 或 Java 配置文件显式地定义 URL 模式与处理器之间的映射关系。适合那些不使用注解的情况。
 * 		ControllerClassNameHandlerMapping：根据控制器类名的一部分来推断 URL 模式。例如，对于名为 MyController 的控制器，默认会映射到 /my。
 * 		DefaultAnnotationHandlerMapping：这是一个较旧的实现，已经被 RequestMappingHandlerMapping 替代。它也用于基于注解的映射，但在 Spring 3.1 之后就不再推荐使用。
 * 		RouterFunctionMapping：支持基于函数式编程风格的 WebFlux 和 Servlet 应用程序中的路由配置。
 *
 * 	3. 工作流程
 * 		当 DispatcherServlet 收到一个 HTTP 请求时，它会依次查询所有注册的 HandlerMapping 实例，直到找到一个能处理该请求的处理器为止。每个 HandlerMapping 实现都遵循以下基本步骤：
 *
 * 		1) 检查是否支持当前请求：某些 HandlerMapping 可能只支持特定类型的请求（例如，仅限 GET 请求），因此首先需要确认它们能否处理当前请求。
 * 		2) 查找处理器：根据请求信息（如 URL、HTTP 方法等），尝试找到一个或多个匹配的处理器候选者。
 * 		3) 返回 HandlerExecutionChain：一旦找到了合适的处理器，HandlerMapping 将返回一个包含处理器及其相关拦截器（Interceptor）的 HandlerExecutionChain 对象。如果没有找到匹配项，则返回 null。
 * 		4) 执行拦截器：DispatcherServlet 在调用处理器之前会先执行链中的预处理拦截器，在处理器执行完毕后还会执行后处理拦截器。
 * 		5) 调用处理器：最后，DispatcherServlet 使用 HandlerAdapter 来调用实际的处理器方法，并获取结果。
 *	4. 自定义 HandlerMapping
 * 		如果你的应用有特殊的需求，比如更复杂的路由规则或者需要结合其他框架一起工作，你可以创建自己的 HandlerMapping 实现。要做到这一点，你需要：
 *
 * 		实现 HandlerMapping 接口：编写一个新的类并实现 HandlerMapping 接口中的方法，特别是 getHandler(HttpServletRequest) 方法。
 * 		注册自定义 HandlerMapping：将你的自定义 HandlerMapping 注册为 Spring 容器中的一个 Bean。可以通过 XML 或者 JavaConfig 来完成。
 *
 *		public class MyCustomHandlerMapping implements HandlerMapping {
 *     		@Override
 *     		public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
 *         		// 自定义逻辑来决定哪个处理器应该处理请求
 *        		 return null; // 返回适当的 HandlerExecutionChain 或 null
 *     		}
 *     		// 其他必要方法...
 * 		}
 * 		然后在配置类中注册：
 * 		        @Configuration
 * 				public class WebConfig implements WebMvcConfigurer {
 *    				 @Bean
 *    			 	public HandlerMapping myCustomHandlerMapping() {
 *        				 return new MyCustomHandlerMapping();
 *     				}
 *     				// 其他配置...
 * 				}
 * 5. 优先级与顺序
 * 		多个 HandlerMapping 实例可能会同时存在于同一个应用中，因此有必要定义它们之间的优先级。默认情况下，HandlerMapping 的顺序是由它们在 Spring 容器中注册的顺序决定的。
 * 		不过，你可以通过设置 order 属性来明确指定优先级，较低的数值表示更高的优先级。
 *
 * 6. 最佳实践
 * 		选择合适的 HandlerMapping：根据应用的具体需求选择最合适的 HandlerMapping 实现。对于大多数现代应用来说，RequestMappingHandlerMapping 已经足够好用了。
 * 		避免过度定制：除非绝对必要，否则尽量不要自定义 HandlerMapping。利用现有的功能和特性往往更加高效且易于维护。
 * 		理解默认行为：了解 Spring MVC 默认使用的 HandlerMapping 和其行为，可以帮助你更好地调试和优化应用。
 * 		使用注解驱动的方式：尽可能采用基于注解的方式来配置路由和处理器，这不仅简化了代码，还提高了可读性和灵活性。
 *
 * </p>
 * Interface to be implemented by objects that define a mapping between
 * requests and handler objects.
 * <br> 接口类，定义 请求 和 处理器对象 之间的映射。
 *
 * <p>This class can be implemented by application developers, although this is not
 * necessary, as {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping}
 * and {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping}
 * are included in the framework. The former is the default if no
 * HandlerMapping bean is registered in the application context.
 * <br> 该接口可以被应用开发者实现，虽然这不是必须的，因为框架中已经包含了
 * {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping}
 * 和 {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping}
 * 。前者是如果没有在应用上下文中注册 HandlerMapping bean 的默认选项。
 *
 * <p>HandlerMapping implementations can support mapped interceptors but do not
 * have to. A handler will always be wrapped in a {@link HandlerExecutionChain}
 * instance, optionally accompanied by some {@link HandlerInterceptor} instances.
 * The DispatcherServlet will first call each HandlerInterceptor's
 * {@code preHandle} method in the given order, finally invoking the handler
 * itself if all {@code preHandle} methods have returned {@code true}.
 *
 * <p>The ability to parameterize this mapping is a powerful and unusual
 * capability of this MVC framework. For example, it is possible to write
 * a custom mapping based on session state, cookie state or many other
 * variables. No other MVC framework seems to be equally flexible.
 *
 * <p>Note: Implementations can implement the {@link org.springframework.core.Ordered}
 * interface to be able to specify a sorting order and thus a priority for getting
 * applied by DispatcherServlet. Non-Ordered instances get treated as the lowest priority.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @see org.springframework.core.Ordered
 * @see org.springframework.web.servlet.handler.AbstractHandlerMapping
 * @see org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
 * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
 */
public interface HandlerMapping {

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains the mapped
	 * handler for the best matching pattern.
	 * <br> 请求属性名，包含最佳匹配模式的映射处理器。
	 * @since 4.3.21
	 */
	String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains the path
	 * used to look up the matching handler, which depending on the configured
	 * {@link org.springframework.web.util.UrlPathHelper} could be the full path
	 * or without the context path, decoded or not, etc.
	 * @since 5.2
	 * @deprecated as of 5.3 in favor of
	 * {@link org.springframework.web.util.UrlPathHelper#PATH_ATTRIBUTE} and
	 * {@link org.springframework.web.util.ServletRequestPathUtils#PATH_ATTRIBUTE}.
	 * To access the cached path used for request mapping, use
	 * {@link org.springframework.web.util.ServletRequestPathUtils#getCachedPathValue(ServletRequest)}.
	 */
	@Deprecated
	String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath";

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains the path
	 * within the handler mapping, in case of a pattern match, or the full
	 * relevant URI (typically within the DispatcherServlet's mapping) else.
	 * <p>Note: This attribute is not required to be supported by all
	 * HandlerMapping implementations. URL-based HandlerMappings will
	 * typically support it, but handlers should not necessarily expect
	 * this request attribute to be present in all scenarios.
	 */
	String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains the
	 * best matching pattern within the handler mapping.
	 * <p>Note: This attribute is not required to be supported by all
	 * HandlerMapping implementations. URL-based HandlerMappings will
	 * typically support it, but handlers should not necessarily expect
	 * this request attribute to be present in all scenarios.
	 */
	String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";

	/**
	 * Name of the boolean {@link HttpServletRequest} attribute that indicates
	 * whether type-level mappings should be inspected.
	 * <p>Note: This attribute is not required to be supported by all
	 * HandlerMapping implementations.
	 */
	String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains the URI
	 * templates map, mapping variable names to values.
	 * <p>Note: This attribute is not required to be supported by all
	 * HandlerMapping implementations. URL-based HandlerMappings will
	 * typically support it, but handlers should not necessarily expect
	 * this request attribute to be present in all scenarios.
	 */
	String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains a map with
	 * URI variable names and a corresponding MultiValueMap of URI matrix
	 * variables for each.
	 * <p>Note: This attribute is not required to be supported by all
	 * HandlerMapping implementations and may also not be present depending on
	 * whether the HandlerMapping is configured to keep matrix variable content
	 */
	String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains the set of
	 * producible MediaTypes applicable to the mapped handler.
	 * <p>Note: This attribute is not required to be supported by all
	 * HandlerMapping implementations. Handlers should not necessarily expect
	 * this request attribute to be present in all scenarios.
	 */
	String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";


	/**
	 * Whether this {@code HandlerMapping} instance has been enabled to use parsed
	 * {@link org.springframework.web.util.pattern.PathPattern}s in which case
	 * the {@link DispatcherServlet} automatically
	 * {@link org.springframework.web.util.ServletRequestPathUtils#parseAndCache parses}
	 * the {@code RequestPath} to make it available for
	 * {@link org.springframework.web.util.ServletRequestPathUtils#getParsedRequestPath
	 * access} in {@code HandlerMapping}s, {@code HandlerInterceptor}s, and
	 * other components.
	 * @since 5.3
	 */
	default boolean usesPathPatterns() {
		return false;
	}

	/**
	 * Return a handler and any interceptors for this request. The choice may be made
	 * on request URL, session state, or any factor the implementing class chooses.
	 * <p>The returned HandlerExecutionChain contains a handler Object, rather than
	 * even a tag interface, so that handlers are not constrained in any way.
	 * For example, a HandlerAdapter could be written to allow another framework's
	 * handler objects to be used.
	 * <p>Returns {@code null} if no match was found. This is not an error.
	 * The DispatcherServlet will query all registered HandlerMapping beans to find
	 * a match, and only decide there is an error if none can find a handler.
	 * @param request current HTTP request
	 * @return a HandlerExecutionChain instance containing handler object and
	 * any interceptors, or {@code null} if no mapping found
	 * @throws Exception if there is an internal error
	 */
	@Nullable
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

}
